﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;

namespace Manager.Tools.DnsSecKeygen
{
    /// <summary>
    /// dnssec-keygen user interface form
    /// </summary>
    public partial class dnsSecKeygenForm : Form
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="dnsSecKeygenForm"/> class.
        /// </summary>
        public dnsSecKeygenForm()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Handles the SelectedIndexChanged event of the algorithmComboBox control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void algorithmComboBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            SetKeySize();
        }

        /// <summary>
        /// Sets the keysize control's properties according to the selected algorithms.
        /// </summary>
        private void SetKeySize()
        {
            keysizeNumericUpDown.Enabled = true;
            generatorComboBox.Enabled = false;

            switch (algorithmComboBox.Text)
            {
                case "RSAMD5":
                    keysizeNumericUpDown.Minimum = 512;
                    keysizeNumericUpDown.Maximum = 2048;
                    keysizeNumericUpDown.Increment = 1;
                    break;
                case "RSASHA1":
                    keysizeNumericUpDown.Minimum = 512;
                    keysizeNumericUpDown.Maximum = 2048;
                    keysizeNumericUpDown.Increment = 1;
                    break;
                case "DSA":
                    keysizeNumericUpDown.Minimum = 512;
                    keysizeNumericUpDown.Maximum = 1024;
                    keysizeNumericUpDown.Increment = 64;
                    break;
                case "DH":
                    keysizeNumericUpDown.Minimum = 128;
                    keysizeNumericUpDown.Maximum = 4096;
                    keysizeNumericUpDown.Increment = 1;
                    generatorComboBox.Enabled = true;
                    break;
                case "HMAC-MD5":
                    keysizeNumericUpDown.Minimum = 1;
                    keysizeNumericUpDown.Maximum = 512;
                    keysizeNumericUpDown.Increment = 1;
                    break;
                case "HMAC-SHA1":
                    keysizeNumericUpDown.Minimum = 1;
                    keysizeNumericUpDown.Maximum = 160;
                    keysizeNumericUpDown.Increment = 1;
                    break;
                case "HMAC-SHA224":
                    keysizeNumericUpDown.Minimum = 1;
                    keysizeNumericUpDown.Maximum = 224;
                    keysizeNumericUpDown.Increment = 1;
                    break;
                case "HMAC-SHA256":
                    keysizeNumericUpDown.Minimum = 1;
                    keysizeNumericUpDown.Maximum = 256;
                    keysizeNumericUpDown.Increment = 1;
                    break;
                case "HMAC-SHA384":
                    keysizeNumericUpDown.Minimum = 1;
                    keysizeNumericUpDown.Maximum = 384;
                    keysizeNumericUpDown.Increment = 1;
                    break;
                case "HMAC-SHA512":
                    keysizeNumericUpDown.Minimum = 1;
                    keysizeNumericUpDown.Maximum = 512;
                    keysizeNumericUpDown.Increment = 1;
                    break;
                default:
                    keysizeNumericUpDown.Enabled = false;
                    break;
            }
        }

        /// <summary>
        /// Handles the Click event of the generateButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void generateButton_Click(object sender, EventArgs e)
        {
            string keygenPath = Path.Combine(Properties.Settings.Default.BindDirectoryPath, @"bin\dnssec-keygen.exe");
            string argument = GetArguments();

            string[] startParams = {keygenPath, argument};

            keygenBackgroundWorker.RunWorkerAsync(startParams);
        }

        /// <summary>
        /// Gets the arguments of the tool.
        /// </summary>
        /// <returns></returns>
        private string GetArguments()
        {
            StringBuilder arguments = new StringBuilder();
            
            // Mandatory arguments
            arguments.AppendFormat("-a {0} ", algorithmComboBox.Text);
            arguments.AppendFormat("-b {0} ", keysizeNumericUpDown.Value);
            arguments.AppendFormat("-n {0} ", nametypeComboBox.Text);

            // Optional arguments
            if(!string.IsNullOrEmpty(classComboBox.Text))
            {
                arguments.AppendFormat("-c {0} ", classComboBox.Text);
            }
            if(largeExponentCheckBox.Checked)
            {
                arguments.Append("-e ");
            }
            if(keySigningKeyCheckBox.Checked)
            {
                arguments.Append("-f ");
            }
            if(generatorComboBox.Enabled)
            {
                arguments.AppendFormat("-g {0} ", generatorComboBox.Text);
            }
            if (!string.IsNullOrEmpty(typeComboBox.Text))
            {
                arguments.AppendFormat("-t {0} ", typeComboBox.Text);
            }
            if(!string.IsNullOrEmpty(protocolComboBox.Text))
            {
                arguments.AppendFormat("-p {0} ", protocolComboBox.Text);
            }
            if(strengthNumericUpDown.Value>0)
            {
                arguments.AppendFormat("-s {0} ", strengthNumericUpDown.Text);
            }
            if(verboseCheckBox.Checked)
            {
                arguments.Append("-v ");
            }
            if(keyInsteadOfDnsKeyCheckBox.Checked)
            {
                arguments.Append("-k ");
            }

            arguments.Append(keyNameTextBox.Text);

            return arguments.ToString();
        }

        /// <summary>
        /// Handles the DoWork event of the keygenBackgroundWorker control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.DoWorkEventArgs"/> instance containing the event data.</param>
        private void keygenBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            string[] startParams = (string[])e.Argument;

            ProcessStartInfo startInfo = new ProcessStartInfo(startParams[0], startParams[1]);
            startInfo.CreateNoWindow = true;
            startInfo.ErrorDialog = false;
            startInfo.RedirectStandardOutput = true;
            startInfo.UseShellExecute = false;

            Process process = Process.Start(startInfo);
            using(StreamReader reader = process.StandardOutput)
            {
                e.Result = reader.ReadToEnd();
            }
        }

        /// <summary>
        /// Handles the RunWorkerCompleted event of the keygenBackgroundWorker control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.RunWorkerCompletedEventArgs"/> instance containing the event data.</param>
        private void keygenBackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            resultTextBox.Text = e.Result.ToString();
        }

        /// <summary>
        /// Handles the Click event of the copyButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void copyButton_Click(object sender, EventArgs e)
        {
            Clipboard.SetText(resultTextBox.Text);
        }
    }
}
